﻿using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Reflection;
using System.Threading.Tasks;

namespace Tetris {
    public class Utils {
        public static SPList EnsureList(String Name, String Description, SPListTemplateType type, bool hidden = false) {
            SPWeb w = SPContext.Current.Web;
            w.AllowUnsafeUpdates = true;
            
            SPList lReturn = null;

            try  {	        
                lReturn = w.Lists[Name];		
        	} catch {
                Guid lId = w.Lists.Add(Name, Description, type);
                lReturn = w.Lists[lId];
                w.Update();
            }

            if (hidden && !lReturn.Hidden) {
                lReturn.Hidden = hidden;
                w.Update();
            }

            w.AllowUnsafeUpdates = false;
            return lReturn;
        }

        public static SPField EnsureField(SPList l, String Name, SPFieldType type) {

            try {
                return l.Fields[Name];
            } catch {
                l.ParentWeb.AllowUnsafeUpdates = true;

                // Create fields with default setup
                SPField f = null;

                //if (type == SPFieldType.User) {
                //    String userFieldTemplate = "<Field Type='User' List='UserInfo' ShowField='Title' DisplayName='<FIELDNAME>' Name='<FIELDNAME>' />";
                //    l.Fields.AddFieldAsXml(userFieldTemplate.Replace("<FIELDNAME>", Name));
                    
                //} else {

                    switch (type) {
                        case SPFieldType.Text:
                            f = l.Fields.CreateNewField(SPFieldType.Text.ToString(), Name);
                            break;

                        case SPFieldType.Number:
                            f = l.Fields.CreateNewField(SPFieldType.Number.ToString(), Name);
                            ((SPFieldNumber)f).DisplayFormat = SPNumberFormatTypes.NoDecimal;
                            break;

                        case SPFieldType.DateTime:
                            f = l.Fields.CreateNewField(SPFieldType.DateTime.ToString(), Name);
                            ((SPFieldDateTime)f).DisplayFormat = SPDateTimeFieldFormatType.DateOnly;
                            break;

                        case SPFieldType.User:
                            f = l.Fields.CreateNewField(SPFieldType.User.ToString(), Name);
                            ((SPFieldUser)f).SelectionMode = SPFieldUserSelectionMode.PeopleOnly;
                            break;
                    }

                    // Add Field to field collection
                    l.Fields.Add(f);
                //}

                l.Update();

                l.ParentWeb.AllowUnsafeUpdates = false;
                return l.Fields[Name];
            }
        }

        /// <summary>
        /// CssRegistration factory
        /// </summary>
        /// <param name="sPath">Path to css</param>
        /// <returns>A CssRegistration object that will be summed up with other css ressources by SharePoint</returns>
        public static CssRegistration CreateCss(String sPath)
        {
            Assembly assemblyInfo = Assembly.GetExecutingAssembly();
            return CreateCss(sPath, false, assemblyInfo);
        }

        /// <summary>
        /// CssRegistration factory
        /// </summary>
        /// <param name="sPath">Path to css</param>
        /// <param name="genHash">Hash generation indicator</param>
        /// <returns>A CssRegistration object that will be summed up with other css ressources by SharePoint.
        /// If hash = true then a #v=... suffix will be added to the path.
        /// in debug mode the hash will be randomly generated so updates are always visible to the developper
        /// in runtime mode the hash is based on the AssemblyFileVersion and ensures updates for all customers
        /// </returns>
        public static CssRegistration CreateCss(String sPath, bool genHash)
        {
            Assembly assemblyInfo = Assembly.GetExecutingAssembly();
            return CreateCss(sPath, genHash, assemblyInfo);
        }

        /// <summary>
        /// This is where the CssRegistration factory instanciation is performed
        /// </summary>
        /// <param name="sPath">Path to Css</param>
        /// <param name="genHash">Need to generate a hash</param>
        /// <param name="assemblyInfo">AssemblyInfo, usually the calling Assembly</param>
        /// <returns>A CssRegistration object that will be summed up with other css ressources by SharePoint.
        /// If hash = true then a #v=... suffix will be added to the path.
        /// in debug mode the hash will be randomly generated so updates are always visible to the developper
        /// in runtime mode the hash is based on the AssemblyFileVersion and ensures updates for all customers
        /// </returns>
        private static CssRegistration CreateCss(String sPath, bool genHash, Assembly assemblyInfo)
        {
            String hash = String.Format("?v={0}", GetVersion(assemblyInfo));
#if (DEBUG)
            hash = String.Format("?v={0}", GetRandomHash());
#endif

            if (!genHash)
            {
                hash = "";
            }

            CssRegistration css = new CssRegistration()
            {
                Name = sPath + hash
            };
            return css;
        }

        /// <summary>
        /// ScriptLink factory
        /// </summary>
        /// <param name="sPath">Path to Javascript file</param>
        /// <returns>A ScriptLink object that will be summed up with other javascript ressources by SharePoint</returns>
        public static ScriptLink CreateJs(String sPath)
        {
            Assembly assemblyInfo = Assembly.GetExecutingAssembly();
            return CreateJs(sPath, false, assemblyInfo);
        }

        /// <summary>
        /// ScriptLink factory
        /// </summary>
        /// <param name="sPath">Path to Javascript file</param>
        /// <param name="genHash">Hash generation indicator</param>
        /// <returns>A ScriptLink object that will be summed up with other javascript ressources by SharePoint</returns>
        public static ScriptLink CreateJs(String sPath, bool genHash)
        {
            Assembly assemblyInfo = Assembly.GetExecutingAssembly();
            return CreateJs(sPath, genHash, assemblyInfo);
        }

        /// <summary>
        /// This is where the ScriptLink factory instanciation is performed
        /// </summary>
        /// <param name="sPath">Path to Javascript file</param>
        /// <param name="genHash">Need to generate a hash</param>
        /// <param name="assemblyInfo">AssemblyInfo, usually the calling Assembly</param>
        /// <returns>A ScriptLink object that will be summed up with other css ressources by SharePoint.
        /// If hash = true then a #v=... suffix will be added to the path.
        /// in debug mode the hash will be randomly generated so updates are always visible to the developper
        /// in runtime mode the hash is based on the AssemblyFileVersion and ensures updates for all customers
        /// </returns>
        public static ScriptLink CreateJs(String sPath, bool genHash, Assembly assemblyInfo)
        {
            String hash = String.Format("?v={0}", GetVersion(assemblyInfo));
#if (DEBUG)
            hash = String.Format("?v={0}", GetRandomHash());
#endif

            if (!genHash)
            {
                hash = "";
            }

            ScriptLink sl = new ScriptLink()
            {
                Name = sPath + hash,
                Localizable = false
            };
            return sl;
        }

        public static String GetHash()
        {
            String hash = String.Format("?v={0}", GetVersion(Assembly.GetExecutingAssembly()));
#if (DEBUG)
            hash = String.Format("?v={0}", GetRandomHash());
#endif
            return hash;
        }

        /// <summary>
        /// Return the FileVersion of an Assembly that will be used to produce file Hashes
        /// This avoid clearing the webbrowser cache for final users after a new version is deployed
        /// </summary>
        /// <param name="assemblyInfo"></param>
        /// <returns>The assembly fileversion</returns>
        public static String GetVersion(Assembly assemblyInfo)
        {
            FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assemblyInfo.Location);
            return fileVersionInfo.FileVersion;
        }

        /// <summary>
        /// Produce a random file Hashes
        /// This avoid clearing the webbrowser cache for developpers for each debugging session
        /// </summary>
        /// <returns>A random generated string</returns>
        public static String GetRandomHash()
        {
            return Guid.NewGuid().GetHashCode().ToString();
        }
    }
}
